package com.study.license.core.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RuntimeUtil;
import com.study.license.core.model.LicenseCreatorParam;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;

@Slf4j
public class KeyToolUtil {
    private static final String DefaultPrivateName="wonder-private-key";
    private static final String DefaultPublicName="wonder-public-key";
    private static final String DefaultValidity="3650";
    private static final String DefaultKeySize="1024";
    private static final String DefaultPassword="unsafe_default";
    private static final String DefaultFilePath="";
    //KeyTool目录
    private static String keyToolPath="";
    //生成私钥库命令
    private static final String generatePrivateKeyCommand=Paths.get(keyToolPath,"keytool").toAbsolutePath()+" -genkey -alias %s -keysize %s -keystore %s.store -validity %s -storepass %s -keypass %s -dname \"CN=%s,OU=%s,O=%s,L=%s,ST=%s,C=%s\"";
    //生成证书命令
    private static final String generateCertCommand=Paths.get(keyToolPath,"keytool").toAbsolutePath()+" -export -alias %s -file %s -keystore %s.store -storepass %s";
    //导入公钥库命令
    private static final String generatePublicKeyCommand=Paths.get(keyToolPath,"keytool").toAbsolutePath()+" -import -alias %s -file %s -keystore %s.store -storepass %s -noprompt";

    /**
     * 生成密钥对 返回结果路径下privateKeyName.store 和 publicKeyName.store
     * @param privateKeyName 私钥别称：为空wonder-private-key
     * @param publicKeyName 公钥别称：为空wonder-public-key
     * @param privatePassword 私钥密码：为空unsafe_default
     * @param publicPassword 公钥密码：为空和私钥密码一致
     * @param validity 密钥库生效时长 默认3650
     * @param keySize 密钥库大小 默认1024
     * @param filePath 生成目录
     * @return 生成目录绝对路径
     */
    public static String generateKeyPair(String privateKeyName,String publicKeyName,String privatePassword,String publicPassword,String validity,String keySize,String filePath){
        filePath = Func.toStr(filePath, DefaultFilePath);
        privateKeyName = Func.toStr(privateKeyName, DefaultPrivateName);
        publicKeyName = Func.toStr(publicKeyName, DefaultPublicName);
        privatePassword = Func.toStr(privatePassword, DefaultPassword);
        publicPassword = Func.toStr(publicPassword, privatePassword);
        validity = Func.toStr(validity, DefaultValidity);
        keySize = Func.toStr(keySize, DefaultKeySize);


        String formatPrivateKeyCommand = String.format(generatePrivateKeyCommand, privateKeyName, keySize, Paths.get(filePath , privateKeyName).toAbsolutePath(), validity, privatePassword, privatePassword, privateKeyName, privateKeyName, privateKeyName, privateKeyName, privateKeyName, privateKeyName);
        Path tempCertPath = Paths.get(filePath, "temp_public.cer");
        String formatCertCommand = String.format(generateCertCommand, privateKeyName, tempCertPath.toAbsolutePath(), Paths.get(filePath , privateKeyName).toAbsolutePath() , privatePassword);
        String formatPublicKeyCommand = String.format(generatePublicKeyCommand, publicKeyName, tempCertPath.toAbsolutePath(), Paths.get(filePath , publicKeyName).toAbsolutePath(), publicPassword);

        execCommand(formatPrivateKeyCommand);
        execCommand(formatCertCommand);
        execCommand(formatPublicKeyCommand);
        FileUtil.del(tempCertPath);
        return filePath;
    }

    private static String execCommandWithResult(String command){
        Process commandProcess =  execCommand(command);
        log.error("执行 {} 获取输出结果",command);
        StringBuilder resultBuilder=new StringBuilder();
        try(BufferedReader input = new BufferedReader(new InputStreamReader(commandProcess.getInputStream()))){
            String line;
            while ((line = input.readLine()) != null) {
                resultBuilder.append(line).append("\n");
            }
        } catch (Exception e) {
            log.error("执行 {} 获取输出结果错误",command, e);
        }
        log.error("执行 {} 获取输出结果结束",command,resultBuilder);
        return resultBuilder.toString();
    }
    private static Process execCommand(String command){
        Process commandProcess = null;
        try {
            log.error("执行 {}",command);
            commandProcess=RuntimeUtil.exec(command);
            commandProcess.waitFor();
            int exitValue = commandProcess.exitValue();
            log.error("执行 {} 结束,退出值：{}",command,exitValue);
        } catch (InterruptedException e) {
            log.error("执行 {} 失败:{}",command,e);
        }
        return commandProcess;
    }

    public static void generateKeyPair(LicenseCreatorParam param) {
        String filePath = Paths.get(AuthUtil.getTenantId(),AuthUtil.getUserId()+"",System.currentTimeMillis()+"").toAbsolutePath().toString();
        FileUtil.mkdir(filePath);
        String keyPairPath = generateKeyPair(param.getPrivateAlias(), param.getPrivateAlias() + "-public", param.getKeyPass(), param.getStorePass(), null, null, filePath);
        param.setPrivateKeysStorePath(Paths.get(keyPairPath,param.getPrivateAlias()+".store").toAbsolutePath().toString());
        param.setPublicKeysStorePath(Paths.get(keyPairPath,param.getPrivateAlias() + "-public.store").toAbsolutePath().toString());
    }
}
